<!--
 * @Description: 
 * @Author: ldx
 * @Date: 2023-03-02 21:05:41
 * @LastEditors: ldx
 * @LastEditTime: 2023-04-24 09:34:27
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }

    #canvas {
      background: url(./images/sky.jpeg);
      background-size: cover;
    }
  </style>
</head>

<body>
  <script id="vertex" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    attribute float a_PointSize;
    void main(){
      // 顶点位置
      gl_Position = a_Position;
      // 顶点大小
      gl_PointSize = a_PointSize;
    }
  </script>
  <script id="fragment" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec4 u_FragColor;
    void main(){
      float dist = distance(vec2(0.5, 0.5), gl_PointCoord);
      if(dist < 0.5){
        // 片元颜色
       gl_FragColor = u_FragColor;
      }else{
        discard;
      }
    }
  </script>
  <canvas id="canvas"></canvas>
  <script type="module">
    import { initProgram } from '../jsm/utils.js'
    import Track from '../jsm/Track.js'
    import Compose from '../jsm/Compose.js'
    const canvas = document.querySelector('#canvas')
    // 设置canvas容器的宽高
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    // 获取webgl上下文
    const gl = canvas.getContext('webgl');
    // 声明将来用来清空绘图区的颜色。分别对应r,g,b,a
    gl.clearColor(0, 0, 0, 0)
    // 使用之前声明的颜色，清空绘图区
    gl.clear(gl.COLOR_BUFFER_BIT)

    // 初始化程序对象
    initProgram(gl)
    const points = []
    // 获取attribute变量并修改
    const a_Position = gl.getAttribLocation(gl.program, 'a_Position')
    const a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize')
    // 获取attribute变量并修改
    const u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

    // 获取canvas容器的一半宽高
    const halfW = canvas.clientWidth / 2
    const halfH = canvas.clientHeight / 2

    const compose = new Compose()
    canvas.addEventListener('click', ({ clientX, clientY }) => {
      // 计算webgl坐标系下的鼠标位置
      const x = (clientX - halfW) / halfW
      const y = -(clientY - halfH) / halfH
      const s = Math.random() * 10 + 2 //大小
      const a = 1 // 透明度
      const data = { x, y, s, a }
      points.push(data)
      const track = new Track(data)
      track.start = new Date()
      track.timeLen = 2000
      track.loop = true
      track.keyMap = new Map([
        [
          'a',
          [
            [500, 1],
            [1000, 0],
            [1500, 1],
          ]
        ]
      ])
      compose.add(track)

    })
    // 片元透明度需开启才能生效
    // 设置混合模式的语句
    /**
     * gl.enable(gl.BLEND) 启用混合模式。这将允许绘制的颜色与已经存在于画布上的颜色混合。
     * gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) 设置混合函数。
     * 混合函数指定了如何将新颜色与已经存在于画布上的颜色混合。
     * 在这种情况下，使用的混合函数是常见的"源颜色乘以源alpha + 目标颜色乘以1减去源alpha"混合方式。
     * 这通常用于渲染具有透明度的对象，其中源颜色是新渲染的颜色，目标颜色是已经存在于画布上的颜色，而源alpha指定了新颜色的透明度。
    */
    gl.enable(gl.BLEND)
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    render()
    // 渲染
    function render() {
      gl.clear(gl.COLOR_BUFFER_BIT)
      points.forEach(({ x, y, s, a }) => {
        gl.vertexAttrib2f(a_Position, x, y)
        gl.vertexAttrib1f(a_PointSize, s)
        gl.uniform4fv(u_FragColor, [0.78, 0.88, 0.78, a])
        gl.drawArrays(gl.POINT, 0, 1)
      })
    }
    !(function ani() {
      compose.update(new Date())
      render()
      requestAnimationFrame(ani)
    })()
  </script>
</body>

</html>